package com.linhai.scm.dao.impl;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.DetachedCriteria;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate4.HibernateCallback;
import org.springframework.orm.hibernate4.support.HibernateDaoSupport;

import com.linhai.general.Page;
import com.linhai.scm.dao.IBaseDao;

@SuppressWarnings({"unchecked"})
public abstract class BaseDao<T> extends HibernateDaoSupport implements IBaseDao<T> {
//public class BaseDao<T> extends HibernateDaoSupport implements IBaseDao<T> {
	
	//因为HibernateDaoSupport里的这个方法不会自动加载实例化，所以在BaseDao中实例化他
    @Autowired
    public void setMySessionFactory(SessionFactory sessionFactory){
        super.setSessionFactory(sessionFactory);  
    }
	
	private Class<T> entityClass;
	private String baseHQL;
	
	@SuppressWarnings({"rawtypes"})
	public BaseDao() {
        Type genType = getClass().getGenericSuperclass();
        Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
        entityClass =  (Class)params[0];
        //baseHQL=" from " + entityClass.getCanonicalName()+ " t where 1=1 ";
        baseHQL=" from " + entityClass.getSimpleName()+ " t where 1=1 ";
    }
	
	/**
	 * 增加数据
	 * @param entity 要插入的数据实体
	 * @return 插入后生成的主键
	 */
    public Serializable insert(T entity) {
        return getHibernateTemplate().save(entity);
    }
    
    /**
	 * 删除数据
	 * @param id 要删除的数据实体ID
	 */
    public void delete(Serializable id) {
    	T entity = (T)getHibernateTemplate().get(entityClass, id);
    	if (entity == null){
    		return;
    	}
        getHibernateTemplate().delete(entity);
    }
    
    /**
     * 批量删除
     * @param ids
     */
    public void delete(List<Serializable> ids){
    	for (Serializable id : ids){
    		T entity = (T)getHibernateTemplate().get(entityClass, id);
    		if (entity == null){
    			continue;
    		}
    		getHibernateTemplate().delete(entity);
    	}
    }

    /**
     * 更新数据
     * @param entity 要更新的数据实体
     */
    public void update(T entity) {
        getHibernateTemplate().update(entity);       
    }
    
    /**
	 * 根据条件判断实体是否存在
	 * @param values 要查询的条件
	 * @return
	 */
	public boolean isExist(final Map<String,Object> values){
		return (boolean)getHibernateTemplate().execute(new HibernateCallback<Object>(){
			public Object doInHibernate(Session session) throws HibernateException{
				StringBuffer hql=new StringBuffer("select objID ");
				hql.append(baseHQL);
				if(null!=values){
					for(Map.Entry<String, Object> entry : values.entrySet()){
						hql.append(" and t."+entry.getKey()+"=:"+entry.getKey());
					}
				}
				Query query = session.createQuery(hql.toString());
				if(null!=values){
					for(Map.Entry<String, Object> entry : values.entrySet()){
						query.setParameter(entry.getKey(), entry.getValue());
					}
				}
				return !query.list().isEmpty();
			}
		});
	}
    
    /**
	 * 根据 主键ID 获取实体
	 * @param id 主键
	 * @return 实体
	 */
	public T get(Serializable id) {
		return (T)getHibernateTemplate().get(entityClass, id);
    }
	
	/**
	 * 根据条件，查出实体
	 * @param values 要查询的条件
	 * @return
	 */
	public T get(final Map<String,Object> values){
		return (T)getHibernateTemplate().execute(new HibernateCallback<Object>(){
    		public Object doInHibernate(Session session) throws HibernateException{
    			StringBuffer hql=new StringBuffer(baseHQL);
    			if(null!=values){
	    			for(Map.Entry<String, Object> entry : values.entrySet()){
	    				hql.append(" and t."+entry.getKey()+"=:"+entry.getKey());
	    			}
    			}
    			Query query = session.createQuery(hql.toString());
    			if(null!=values){
	    			for(Map.Entry<String, Object> entry : values.entrySet()){
	    				query.setParameter(entry.getKey(), entry.getValue());
	    			}
    			}
    			return (T)query.getFirstResult();
    		}
    	});
	}
	
	public T get(final String hql,final Object... values){
		return (T)getHibernateTemplate().execute(new HibernateCallback<Object>(){
    		public Object doInHibernate(Session session) throws HibernateException{
    			Query query = session.createQuery(hql);
    			for (int i = 0 ; i < values.length ; i++){
    				query.setParameter(i, values[i]);
    			}
    			return (T)query.uniqueResult();
    		}
    	});	
	}
	
	/**
	 * 根据 主键ID 获取实体
	 * @param id 主键
	 * @return 实体
	 */
	public T load(Serializable id) {
		return (T)getHibernateTemplate().load(entityClass, id);
    }
	
	/**
	 * 获取所有数据集合
	 * @return
	 */
	public List<T> loadAll(){
		return (List<T>)getHibernateTemplate().loadAll(entityClass);
	}
	
	/**
	 * 获取所有数据集合
	 * @param values 要查询的条件
	 * @return 数据集合
	 */
	@SuppressWarnings({"rawtypes"})
	public List<T> getList(Map<String,Object> values){
		Iterator iter=null;
		Object[] obj=null;
		int obj_Length=values.size();
		StringBuffer hql=new StringBuffer(baseHQL);
		if(null!=values && 0<obj_Length){
			for(Map.Entry<String, Object> entry : values.entrySet()){
				hql.append(" and t."+entry.getKey()+"=:"+entry.getKey());
				System.out.println(entry.getKey()+": "+entry.getValue());
			}
			obj=new Object[obj_Length];
			int i=0;
			for(Map.Entry<String, Object> entry : values.entrySet()){
				obj[i]=entry.getValue();
			}
			iter=getHibernateTemplate().iterate(hql.toString(),obj);
		}
		iter=getHibernateTemplate().iterate(hql.toString());
		List<T> list=new ArrayList<T>();
		while(iter.hasNext()){
			list.add((T)iter.next());
		}
		return list;
	}
	
	/**
	 * 获取所有数据集合
	 * @param values hql的参数(如果有)
	 * @return 数据集合
	 */
	@SuppressWarnings({"rawtypes"})
	public List<T> getList(String hql,Object... values){
		Iterator iter=getHibernateTemplate().iterate(hql.toString(),values);
		List<T> list=new ArrayList<T>();
		while(iter.hasNext()){
			list.add((T)iter.next());
		}
		return list;
	}
	
	public List<T> findRowsByCriteria(DetachedCriteria detachedCriteria, int first, int max){
		 return (List<T>)getHibernateTemplate().findByCriteria(detachedCriteria, first, max);
	}
	
	/**
	 * 获取记录条数
	 * @param values 要查询的条件
	 * @return 返回记录条数
	 */
	public int getCount(Map<String,Object> values){
		Object[] obj=null;
		int obj_Length=values.size();
		StringBuffer hql=new StringBuffer("select count(*) ");
		hql.append(baseHQL);
		if(null!=values && 0<obj_Length){
			for(Map.Entry<String, Object> entry : values.entrySet()){
				hql.append(" and t."+entry.getKey()+"=:"+entry.getKey());
				System.out.println(entry.getKey()+": "+entry.getValue());
			}
			obj=new Object[obj_Length];
			int i=0;
			for(Map.Entry<String, Object> entry : values.entrySet()){
				obj[i]=entry.getValue();
			}
			return (int)((List<Object>)getHibernateTemplate().find(hql.toString(), obj)).get(0);
		}
		return (int)((List<Object>)getHibernateTemplate().find(hql.toString())).get(0);
	}
	
	/**
	 * 获取记录条数
	 * @param hql 需要查询的hql语句
	 * @param values hql的参数(如果有)
	 * @return 返回记录条数
	 */
	public int getCount(String hql,Object... values){
		return (int)((List<Object>)getHibernateTemplate().find(hql.toString(), values)).get(0);
	}
	
	/**
     * 使用hql 语句进行分页查询操作
     * @param page 页面信息（页码，单页显示数量 等）
     * @param values 要查询的条件
     * @return 当前页的所有记录
     */
    public List<T> findByPage(final Page page,final Map<String,Object> values){
    	return (List<T>)getHibernateTemplate().execute(new HibernateCallback<Object>(){
    		public Object doInHibernate(Session session) throws HibernateException{
    			StringBuffer hql=new StringBuffer(baseHQL);
    			if(null!=values){
	    			for(Map.Entry<String, Object> entry : values.entrySet()){
	    				hql.append(" and t."+entry.getKey()+"=:"+entry.getKey());
	    				System.out.println(entry.getKey()+": "+entry.getValue());
	    			}
    			}
    			Query query = session.createQuery(hql.toString());
    			if(null!=values){
	    			for(Map.Entry<String, Object> entry : values.entrySet()){
	    				query.setParameter(entry.getKey(), entry.getValue());
	    			}
    			}
    			List<T> result = query.setFirstResult((page.getPageNo()-1)*page.getPageSize()).setMaxResults(page.getPageSize()).list();
    			return result;
    		}
    	});
    }
    
    /**
     * 使用hql 语句进行分页查询操作
     * @param page 页面信息（页码，单页显示数量 等）
     * @param hql 需要查询的hql语句
     * @param values hql的参数(如果有)
     * @return 当前页的所有记录
     */
    public List<T> findByPage(final Page page,final String hql,final Object... values){
    	return (List<T>)getHibernateTemplate().execute(new HibernateCallback<Object>(){
    		public Object doInHibernate(Session session) throws HibernateException{
    			Query query = session.createQuery(hql);
    			for (int i = 0 ; i < values.length ; i++){
    				query.setParameter(i, values[i]);
    			}
    			List<T> result = query.setFirstResult((page.getPageNo()-1)*page.getPageSize()).setMaxResults(page.getPageSize()).list();
    			return result;
    		}
    	});
    }
}
